<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/9/5
 * Time: 9:42
 */

namespace app\api\service;


use app\api\model\OrderProduct;
use app\api\model\Product;
use app\api\model\UserAddress;
use app\lib\exception\OrderException;
use app\lib\exception\UserException;
use think\Db;
use think\Exception;

class Order
{
    //订单的商品列表,客户端传过来的products参数
    protected $oProducts;

    //真实的商品信息(包括库存量)
    protected $products;

    protected $uid;

    public function place($uid,$oProducts)
    {
        //oProduts与products作对比
        //数据库中查询products
        $this->oProducts = $oProducts;
        //根据订单信息查询库中对应商品信息
        $this->products = $this->getProductsByOrder($oProducts);
        $this->uid = $uid;
        //检测库存量
        $status = $this->getOrderStatus();
        //库存量检测
        if (!$status['pass']){
            $status['order_id'] = -1;
            return $status;
        }

        //开始创建订单
        $orderSnap = $this->snapOrder($status);
        $order = $this->createOrder($orderSnap);
        $order['pass'] = true;
        return $order;
    }

    private function createOrder($snap)
    {
        //事务
        Db::startTrans();
        try{
            $orderNo = $this->makeOrderNo();
            $order = new \app\api\model\Order();
            $order->user_id = $this->uid;
            $order->order_no = $orderNo;
            $order->total_price = $snap['orderPrice'];
            $order->total_count = $snap['totalCount'];
            $order->snap_img = $snap['snapImg'];
            $order->snap_name = $snap['snapName'];
            $order->snap_address = $snap['snapAddress'];
            $order->snap_items = json_encode($snap['pStatus']);
            //保存订单信息
            $order->save();

            $orderId = $order->id;
            $create_time = $order->create_time;
            foreach($this->oProducts as &$p)
            {
                $p['order_id'] = $orderId;
            }
            $orderProduct = new OrderProduct();
            $orderProduct->saveAll($this->oProducts);
            //提交事务
            Db::commit();
            return [
                'order_no'=>$orderNo,
                'order_id'=>$orderId,
                'create_time'=>$create_time,
            ];
        }catch (Exception $e){
            //回滚
            Db::rollback();
            throw $e;
        }

    }

    //生成订单号
    public function makeOrderNo()
    {
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn =
            $yCode[intval(date('Y')) - 2017] . strtoupper(dechex(date('m'))) . date(
                'd') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf(
                '%02d', rand(0, 99));
        return $orderSn;
    }

    //生成订单快照
    private function snapOrder($status)
    {
        $snap = [
          'orderPrice'=>0,
          'totalCount'=>0,
          'pStatus'=>[],
          'snapAddress'=>null,
            'snapName'=>'',
            'snapImg'=>'',
        ];
        $snap['orderPrice'] = $status['orderPrice'];
        $snap['totalCount'] = $status['totalCount'];
        $snap['pStatus'] = $status['pStatusArray'];
        $snap['snapAddress'] = json_encode($this->getUserAddress());
        $snap['snapName'] = $this->products[0]['name'];
        $snap['snapImg'] = $this->products[0]['main_img_url'];

        if (count($this->products)>1){
            $snap['snapName'] .='等';
        }
        return $snap;
    }

    private function getUserAddress()
    {
        $userAddress = UserAddress::where('user_id','=',$this->uid)
            ->find()
            ->toArray();
        if (!$userAddress)
        {
            throw new UserException([
                'msg'=>'用户收货地址不存在',
                'errorCode'=>60001,
            ]);
        }
        return $userAddress;
    }

    //根据订单id再次检测库存(支付时订单库存再次检测)
    public function checkOrderStock($orderId){
        $oProducts = OrderProduct::where('order_id','=',$orderId)
            ->select();
        $this->oProducts;
        $this->products = $this->getProductsByOrder($oProducts);
        $status = $this->getOrderStatus();
        return $status;
    }

    //对比客户端与库存的数据,库存量那个检测
    private function getOrderStatus()
    {
        $status = [
            'pass'=>true,
            'orderPrice'=>0,
            'totalCount'=>0,
            'pStatusArray'=>[],
        ];

        foreach ($this->oProducts as $oProduct)
        {
            $pStatus = $this->getProductStatus(
                $oProduct['product_id'],$oProduct['count'],$this->products
            );
            if (!$pStatus['haveStock']){
                $status['pass'] = false;
            }
            $status['orderPrice'] += $pStatus['totalPrice'];
            $status['totalCount'] += $pStatus['count'];
            array_push($status['pStatusArray'],$pStatus);
        }
        return $status;
    }

    private function getProductStatus($oPid,$oCount,$products)
    {
        $pIndex = -1;
        $pStatus = [
            'id' => null,
            'haveStock' => false,
            'count' => 0,
            'name' => '',
            'totalPrice' => 0,
        ];
        for ($i = 0; $i < count($products); $i++) {
            if ($oPid == $products[$i]['id']) {
                    $pIndex = $i;
            }
        }

        if ($pIndex == -1){
            //客户端传递的product_id有可能不存在
            throw new OrderException([
                'msg'=>'id为'.$oPid.'商品不错在,创建订单失败',
            ]);
        }else{
            $product = $products[$pIndex];
            $pStatus['id'] = $product['id'];
            $pStatus['name'] = $product['name'];
            $pStatus['count'] = $oCount;
            $pStatus['totalPrice'] = $oCount*$product['price'];
            if ($product['stock'] - $oCount >= 0){
                $pStatus['haveStock'] = true;
            }
        }

        return $pStatus;
    }


    /*根据订单信息查找真实的商品信息*/
    private function getProductsByOrder($oProducts)
    {
//        foreach ($oProducts as $oProduct){
//            //循环的查询数据库
//        }
        $oPids = [];//商品Id号
        foreach ($oProducts as $item){
            array_push($oPids,$item['product_id']);
        }
        $products = Product::all($oPids);
        $products = collection($products);
        $products = $products ->visible(['id','price','stock','name','main_img_url'])->toArray();//设置查找的的字段
        return $products;
    }
}